package com.kersci.heartratereader

import android.bluetooth.BluetoothAdapter
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.content.pm.PackageManager
import android.location.LocationManager
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.os.Message
import android.provider.Settings
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.activity_main.*
import com.clj.fastble.BleManager
import com.kersci.heartratereader.utils.DeviceManager
import com.kersci.heartratereader.utils.DisplayUtil
import com.safframework.log.L

class MainActivity : AppCompatActivity(), DeviceManager.DeviceChangeListener, DeviceManager.ScanEventListener {
    companion object {
        const val REQUEST_CODE_OPEN_GPS = 1
        const val REQUEST_CODE_PERMISSION_LOCATION = 2
        const val EVENT_DIALOG_DISMISS = DeviceManager.EVENT_MAX_DEVICE_ID + 1
    }

    private lateinit var deviceHandler: Handler
    private lateinit var dialog: AutoHideBottomUIDialog
    private lateinit var viewManager: LinearLayoutManager
    private lateinit var deviceClickListener: BleDeviceItemClickListener
    private lateinit var deviceAdapter: BleDeviceListAdapter

    private var isDialogShowed = false

    override fun onDeviceChanged(event: Int) {
        deviceHandler.sendEmptyMessage(event)
    }

    override fun onScanEventChanged(event: Int) {
        deviceHandler.sendEmptyMessage(event)
    }

    private fun handleDeviceScanEventChanged(event: Int) {
        if (event > DeviceManager.EVENT_MAX_DEVICE_ID) {
            // TODO: refresh the UI to show BLE device
        } else {
            L.d(DeviceManager.getEventMessage(this, event))
            if (dialog != null && isDialogShowed) {
                dialog.setScanStatus(DeviceManager.getEventMessage(this, event))
            }

            when (event) {
                DeviceManager.EVENT_SCAN_FINISHED -> {
                    dialog.dismiss()
                    isDialogShowed = false
                    refreshUI()
                }
            }
        }
    }

    private fun initDialog() {
        dialog = AutoHideBottomUIDialog(this)
        dialog.setContentView(R.layout.device_scan_dialog)
        dialog.setDialogHeight((DisplayUtil.getScreenSizeHeight(this) * 0.6f).toInt())
        dialog.setDialogWidth((DisplayUtil.getScreenSizeWidth(this) * 0.9f).toInt())
        dialog.setOnDismissListener(DialogInterface.OnDismissListener { dialog ->
            deviceHandler.sendEmptyMessage(EVENT_DIALOG_DISMISS)
        })
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        if (!BleManager.getInstance().isSupportBle) {
            AlertDialog.Builder(this).apply {
                setTitle(R.string.warning_not_support_ble)
                setMessage(R.string.not_support_ble)
                setCancelable(false)
                setPositiveButton("OK") { _, _ -> {
                    Toast.makeText(this@MainActivity, "click OK", Toast.LENGTH_LONG).show()
                    finish()
                }}
                show()
            }
        }

    }

    override fun onResume() {
        super.onResume()
        deviceHandler = object : Handler(this.mainLooper){
            override fun handleMessage(msg: Message) {
                super.handleMessage(msg)
                handleDeviceScanEventChanged(msg.what)
            }
        }

        initDialog()
        initDeviceListView()
        refreshUI()

        App.instance.getDeviceManager().registerDeviceListener(this)
        App.instance.getDeviceManager().registerScanEventListener(this)

        if (!BleManager.getInstance().isBlueEnable) {
            BleManager.getInstance().enableBluetooth()
        }

        tvAddNewDevice.setOnClickListener {
            startScanBleDevice()
        }
    }

    private fun checkPermission() {
        var bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
        if (!bluetoothAdapter.isEnabled) {
            L.d("Bluetooth is disabled")
            BleManager.getInstance().enableBluetooth()
        }

        var permissions = arrayListOf<String>()
        permissions.add(android.Manifest.permission.ACCESS_FINE_LOCATION)
        var permissionDeniedList = arrayListOf<String>()
        for (permission in permissions) {
            var permissionCheck = ContextCompat.checkSelfPermission(this, permission)
            if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
                onPermissionGranted(permission)
            } else {
                permissionDeniedList.add(permission)
            }
        }

        if (permissionDeniedList.size != 0) {
            ActivityCompat.requestPermissions(this, permissionDeniedList.toTypedArray(), REQUEST_CODE_PERMISSION_LOCATION)
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        when(requestCode) {
            REQUEST_CODE_PERMISSION_LOCATION -> {
                if (grantResults.isNotEmpty()) {
                    for (i in grantResults.indices) {
                        val result = grantResults[i]
                        if (result == PackageManager.PERMISSION_GRANTED) {
                            onPermissionGranted(permissions[i])
                        }
                    }
                }
            }
        }
    }

    private fun checkGPSIsOpened() : Boolean {
        var locationManager = this.getSystemService(Context.LOCATION_SERVICE) as LocationManager
        if (locationManager == null) {
            return false
        } else {
            return locationManager.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER)
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == REQUEST_CODE_OPEN_GPS) {
            if (checkGPSIsOpened()) {
                startService()
            }
        }
    }
    private fun onPermissionGranted(permission: String) {
        when(permission) {
            android.Manifest.permission.ACCESS_FINE_LOCATION -> {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !checkGPSIsOpened()) {
                    var intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
                    startActivityForResult(intent, REQUEST_CODE_OPEN_GPS)
                } else {
                    startService()
                }
            }
        }
    }

    private fun startScanBleDevice() {
        checkPermission()
    }

    private fun startService() {
        var intent = Intent(this, BleDeviceService::class.java)
        intent.action = BleDeviceService.ACTION_START_SEARCHING
        startService(intent)
        dialog.show()
        isDialogShowed = true
    }

    private fun startConnectDevice(position: Int) {
        var intent = Intent(this, DeviceActivity::class.java)
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        intent.putExtra(BleDeviceService.KEY_DEVICE_POSITION, position)
        startActivity(intent)
    }

    private fun initDeviceListView() {
        deviceClickListener = object: BleDeviceItemClickListener {
            override fun onItemClick(position: Int) {
                startConnectDevice(position)
            }
        }

        viewManager = LinearLayoutManager(this)
        viewManager.orientation = LinearLayoutManager.VERTICAL
        deviceAdapter = BleDeviceListAdapter(listOf(), deviceClickListener)
        bleDeviceListView.layoutManager = viewManager
        bleDeviceListView.adapter = deviceAdapter
    }

    private fun refreshUI() {
        val deviceManager = App.instance.getDeviceManager()
        val deviceCount = deviceManager.getDeviceCount()
        if (deviceCount > 0) {
            tvAddNewDevice.visibility = View.INVISIBLE
            layoutDeviceInfo.visibility = View.VISIBLE
            var deviceList = deviceManager.getDevices()
            deviceAdapter.setDeviceList(deviceList)
            deviceAdapter.notifyDataSetChanged()
        } else {
            tvAddNewDevice.visibility = View.VISIBLE
            layoutDeviceInfo.visibility = View.INVISIBLE
        }
    }

    override fun onStop() {
        super.onStop()
        L.d("onStop")
        var intent = Intent(this, BleDeviceService::class.java)
        stopService(intent)
        App.instance.getDeviceManager().unregisterDeviceListener(this)
        App.instance.getDeviceManager().unregisterScanEventListener(this)
    }
}